package com.suman.bbcticker.service;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserFactory;

import android.app.Activity;
import android.appwidget.AppWidgetManager;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.text.Html;
import android.text.Spanned;
import android.util.Log;
import android.util.Xml;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.View.OnClickListener;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.Animation;
import android.view.animation.TranslateAnimation;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.ViewFlipper;

import com.suman.bbcticker.ApplicationStateObjectsHolder;
import com.suman.bbcticker.FeedItem;
import com.suman.bbcticker.R;
import com.suman.bbcticker.RssFeed;
import com.suman.bbcticker.configure.RssFeedPreference;

public class DisplayNewsActivity extends Activity {
	private int mAppWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID;
	private static String NEXT_CLICK = "nextClick";
	private static String PREV_CLICK = "prevClick";
	private static final int IO_BUFFER_SIZE = 4 * 1024;
	private static final String TAG = "DisplayNewsActivity";
	private ViewFlipper flipper;

	private static int currentPageDisplayIndex = 0;

	private final Animation mInFromLeft = new TranslateAnimation(Animation.RELATIVE_TO_PARENT, -1.0f, Animation.RELATIVE_TO_PARENT, 0.0f,
			Animation.RELATIVE_TO_PARENT, 0.0f, Animation.RELATIVE_TO_PARENT, 0.0f);

	private final Animation mOutToLeft = new TranslateAnimation(Animation.RELATIVE_TO_PARENT, 0.0f, Animation.RELATIVE_TO_PARENT, -1.0f,
			Animation.RELATIVE_TO_PARENT, 0.0f, Animation.RELATIVE_TO_PARENT, 0.0f);

	private final Animation mInFromRight = new TranslateAnimation(Animation.RELATIVE_TO_PARENT, 1.0f, Animation.RELATIVE_TO_PARENT, 0.0f,
			Animation.RELATIVE_TO_PARENT, 0.0f, Animation.RELATIVE_TO_PARENT, 0.0f);

	private final Animation mOutToRight = new TranslateAnimation(Animation.RELATIVE_TO_PARENT, 0.0f, Animation.RELATIVE_TO_PARENT, 1.0f,
			Animation.RELATIVE_TO_PARENT, 0.0f, Animation.RELATIVE_TO_PARENT, 0.0f);
	// swipe gesture constants
	private static final int SWIPE_MIN_DISTANCE = 120;
	private static final int SWIPE_MAX_OFF_PATH = 250;
	private static final int SWIPE_THRESHOLD_VELOCITY = 200;
	private GestureDetector gestureDetector;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		try {
			super.onCreate(savedInstanceState);
			setInterpolatorAndDuration(mInFromLeft);
			setInterpolatorAndDuration(mOutToLeft);
			setInterpolatorAndDuration(mInFromRight);
			setInterpolatorAndDuration(mOutToRight);

			currentPageDisplayIndex = 0;
			Intent launchIntent = getIntent();
			Bundle extras = launchIntent.getExtras();
			if (extras != null) {
				mAppWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
			}
			setContentView(R.layout.custom_dialog_activity);
			TextView popupTextView = (TextView) findViewById(R.id.rssbbcpopup_text);

			View scrollView = findViewById(R.id.rssbbcscrollview);

			flipper = ((ViewFlipper) this.findViewById(R.id.flipper));

			// popupTextView.setLongClickable(true);
			scrollView.setLongClickable(true);
			gestureDetector = new GestureDetector(this, new SwipeGestureDetector());
			gestureDetector.setIsLongpressEnabled(true);

			scrollView.setOnTouchListener(new View.OnTouchListener() {
				public boolean onTouch(View v, MotionEvent event) {
					if (gestureDetector.onTouchEvent(event))
						return true;
					else
						return false;

				}

			});

			ImageButton goToSite = (ImageButton) findViewById(R.id.rsspopup_gotosite);
			ImageButton shareButton = (ImageButton) findViewById(R.id.rsspopup_sharebutton);

			RssFeed currentRssFeed = getCurrentRssFeedObjectbasedOnWidgetId();
			createAsyncTaskMapBasedOnWidgetId();
			if (currentRssFeed != null) {
				List<FeedItem> feedList = currentRssFeed.getFeedList();
				final FeedItem feedItem = feedList.get(0);
				popupTextView.setText(styleString(feedItem));
				updateDateAndTimeOfFeed(feedItem);
				startActivityForDisplayingFullNews(feedItem, mAppWidgetId);
				goToSite.setOnClickListener(new OnClickListener() {
					public void onClick(View v) {
						goToWebViewWithUrl(feedItem.getLink());

					}
				});

				shareButton.setOnClickListener(new OnClickListener() {
					public void onClick(View v) {
						launchIntentForSharingNews(feedItem);

					}

				});

			}

			ImageButton closeButton = (ImageButton) findViewById(R.id.rsspopup_closebutton);

			closeButton.setOnClickListener(new OnClickListener() {
				public void onClick(View v) {
					finish();
				}

			});

			flipper.showNext();
		} catch (Throwable t) {
			t.printStackTrace();
		}
	}

	@SuppressWarnings("unchecked")
	private void createAsyncTaskMapBasedOnWidgetId() {
		HashMap<String, AsyncTask> asyncTaskMap = new HashMap<String, AsyncTask>();
		ApplicationStateObjectsHolder.aSyncTaskToWidgetIdMap.put(mAppWidgetId, asyncTaskMap);
	}

	private RssFeed getCurrentRssFeedObjectbasedOnWidgetId() {
		RssFeedPreference rssFeedPreference = ApplicationStateObjectsHolder.preferenceHashMap.get(mAppWidgetId);
		return rssFeedPreference.getCurrentRssFeedObject();
	}

	private void launchIntentForSharingNews(final FeedItem feedItem) {
		Intent intent = new Intent(Intent.ACTION_SEND);
		intent.setType("text/plain");
		intent.putExtra(android.content.Intent.EXTRA_TEXT, feedItem.getTitle() + "\n" + feedItem.getLink());
		startActivity(Intent.createChooser(intent, "Send the news using"));
	}

	private void setInterpolatorAndDuration(Animation anim) {
		mOutToRight.setInterpolator(new AccelerateInterpolator());
		mOutToRight.setDuration(800);
	}

	protected void goToWebViewWithUrl(String link) {
		Intent goToWebViewIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(link));
		startActivity(goToWebViewIntent);
	}

	private void updateDateAndTimeOfFeed(FeedItem feedItem) {
		TextView dateAndTimeView = (TextView) findViewById(R.id.rssbbcpopup_dateandtime);
		dateAndTimeView.setText(formatPublishDate(feedItem.getPubdate()));
	}

	private String formatPublishDate(String pubdate) {
		if (pubdate != null && pubdate.length() >= 4) {
			return pubdate.substring(4);
		}
		return "";
	}

	private Spanned styleString(FeedItem feedItem) {
		return Html.fromHtml("<b>" + feedItem.getTitle() + "</b>" + "<br />" + feedItem.getDescription());
	}

	protected void updateStateOfScreenWithClick(String clickType) {
		try {

			RssFeed currentRssFeed = getCurrentRssFeedObjectbasedOnWidgetId();
			TextView popupTextView = (TextView) findViewById(R.id.rssbbcpopup_text);
			TextView popupTextViewExtended = (TextView) findViewById(R.id.rssbbcpopupextended_text);
			ProgressBar progressBar = (ProgressBar) findViewById(R.id.rssbccprogressbar);
			List<FeedItem> feedList = currentRssFeed.getFeedList();
			progressBar.setVisibility(View.VISIBLE);
			popupTextViewExtended.setVisibility(View.INVISIBLE);

			FeedItem feedItem = null;

			if (NEXT_CLICK.equalsIgnoreCase(clickType)) {
				if (currentPageDisplayIndex != feedList.size() - 1) {
					++currentPageDisplayIndex;
				}
				feedItem = feedList.get(currentPageDisplayIndex);
			} else if (PREV_CLICK.equalsIgnoreCase(clickType)) {
				if (currentPageDisplayIndex != 0) {
					--currentPageDisplayIndex;
				}
				feedItem = feedList.get(currentPageDisplayIndex);
			}

			if (feedItem != null) {
				startActivityForDisplayingFullNews(feedItem, mAppWidgetId);
				popupTextView.setText(styleString(feedItem));
				ImageButton goToSite = (ImageButton) findViewById(R.id.rsspopup_gotosite);
				ImageButton shareButton = (ImageButton) findViewById(R.id.rsspopup_sharebutton);
				final FeedItem feedItemForGoToWeb = feedItem;

				goToSite.setOnClickListener(new OnClickListener() {
					public void onClick(View v) {
						goToWebViewWithUrl(feedItemForGoToWeb.getLink());

					}
				});

				shareButton.setOnClickListener(new OnClickListener() {
					public void onClick(View v) {
						launchIntentForSharingNews(feedItemForGoToWeb);

					}

				});

				updateDateAndTimeOfFeed(feedItem);
			}
		} catch (Throwable t) {
			t.printStackTrace();
		}

	}

	private void startActivityForDisplayingFullNews(FeedItem feedItem, Integer appWidgetId) {
		AsyncTask<String, Void, WebpageStreamDownloadTaskResult> aSyncTaskForDisplayingFullNews = new WebpageStreamDownloadTask().execute(feedItem
				.getLink());
		updateAsyncTaskToWidgetIdMap(feedItem, appWidgetId, aSyncTaskForDisplayingFullNews);

	}

	@SuppressWarnings("unchecked")
	private void updateAsyncTaskToWidgetIdMap(FeedItem feedItem, Integer appWidgetId,
			AsyncTask<String, Void, WebpageStreamDownloadTaskResult> aSyncTaskForDisplayingFullNews) {
		// get the respective map for mappwidgetid
		HashMap<String, AsyncTask> aSyncTaskMap = ApplicationStateObjectsHolder.aSyncTaskToWidgetIdMap.get(appWidgetId);

		Collection<AsyncTask> asyncTaskValues = aSyncTaskMap.values();
		Iterator<AsyncTask> asyncTaskValuesIterator = asyncTaskValues.iterator();
		while (asyncTaskValuesIterator.hasNext()) {
			AsyncTask asyncTask = asyncTaskValuesIterator.next();
			boolean cancel = asyncTask.cancel(true);
			Log.e(TAG, "cancelled status is..." + cancel);
		}
		aSyncTaskMap.clear();
		aSyncTaskMap.put(feedItem.getLink(), aSyncTaskForDisplayingFullNews);
	}

	private class WebpageStreamDownloadTaskResult {
		private String webPageBodyAsString;
		private Bitmap imageBitMap;

		public void setWebPageBodyAsString(String webPageBodyAsString) {
			this.webPageBodyAsString = webPageBodyAsString;
		}

		public String getWebPageBodyAsString() {
			return webPageBodyAsString;
		}

		public void setImageBitMap(Bitmap imageBitMap) {
			this.imageBitMap = imageBitMap;
		}

		public Bitmap getImageBitMap() {
			return imageBitMap;
		}

	}

	private class WebpageStreamDownloadTask extends AsyncTask<String, Void, WebpageStreamDownloadTaskResult> {

		@Override
		protected void onPostExecute(WebpageStreamDownloadTaskResult webpageStreamDownloadTaskResult) {
			if (!isCancelled()) {
				// TODO Auto-generated method stub
				super.onPostExecute(webpageStreamDownloadTaskResult);
				ProgressBar progressBar = (ProgressBar) findViewById(R.id.rssbccprogressbar);
				progressBar.setVisibility(View.GONE);

				// Update textview
				TextView popupTextView = (TextView) findViewById(R.id.rssbbcpopupextended_text);
				popupTextView.setVisibility(View.VISIBLE);
				if (webpageStreamDownloadTaskResult.getWebPageBodyAsString() != null) {
					popupTextView.setText(webpageStreamDownloadTaskResult.getWebPageBodyAsString());
				}
				ImageView imageOfNews = (ImageView) findViewById(R.id.rssbbcpopup_imageofnews);
				if (webpageStreamDownloadTaskResult.getImageBitMap() != null) {
					imageOfNews.setImageBitmap(webpageStreamDownloadTaskResult.getImageBitMap());
				}

			}

		}

		@Override
		protected void onCancelled() {
			super.onCancelled();

			Log.e(TAG, "Cancelled called on WebpageStreamDownloadTask");

		}

		@Override
		protected WebpageStreamDownloadTaskResult doInBackground(String... urls) {
			WebpageStreamDownloadTaskResult webpageStreamDownloadTaskResult = new WebpageStreamDownloadTaskResult();

			if (!isCancelled()) {
				Log.e(TAG, "Trying to download image and webpage..");
				InputStream parsedStream = fetchInputStreamForURL(urls[0]);

				String imageUrl = parsedStream != null ? parseStoryBodyForImageUrl(parsedStream) : null;
				Bitmap bitmap = null;
				try {
					bitmap = imageUrl != null ? BitmapUtils.loadBitmap(imageUrl) : null;
				}catch (Throwable e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}

				String parseStoryBody = parsedStream != null ? parseStoryBody(parsedStream) : null;
				webpageStreamDownloadTaskResult.setImageBitMap(bitmap);
				webpageStreamDownloadTaskResult.setWebPageBodyAsString(parseStoryBody);
			}
			return webpageStreamDownloadTaskResult;

		}

	}

	private String parseStoryBody(InputStream inputStream) {
		String result = "";
		try {
			XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
			factory.setNamespaceAware(true);
			factory.setValidating(false);
			XmlPullParser xpp = factory.newPullParser();
			xpp.setFeature(Xml.FEATURE_RELAXED, true);

			boolean storyBodyDivFound = false;
			xpp.setInput(inputStream, "utf-8");
			int eventType = xpp.getEventType();

			while (eventType != XmlPullParser.END_DOCUMENT) {
				if (eventType == XmlPullParser.START_TAG) {
					if (xpp.getName().equals("div")) {
						if ("storybody".equals(xpp.getAttributeValue(null, "class"))) {

							storyBodyDivFound = true;
						}

					}
				} else if (eventType == XmlPullParser.END_TAG) {

					if (xpp.getName().equals("div")) {

						if (storyBodyDivFound) {

							storyBodyDivFound = false;
							break;

						}

					}

				} else if (eventType == XmlPullParser.TEXT) {
					if (storyBodyDivFound) {
						result += xpp.getText();
					}

				}
				eventType = xpp.next();
			}
		} catch (Throwable t) {
			t.printStackTrace();
		}

		return result;

	}

	public String parseStoryBodyForImageUrl(InputStream inputStream) {
		String result = null;
		try {
			XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
			factory.setNamespaceAware(true);
			factory.setValidating(false);
			XmlPullParser xpp = factory.newPullParser();
			xpp.setFeature(Xml.FEATURE_RELAXED, true);

			xpp.setInput(inputStream, "utf-8");
			int eventType = xpp.getEventType();

			while (eventType != XmlPullParser.END_DOCUMENT) {
				if (eventType == XmlPullParser.START_TAG) {
					if (xpp.getName().equals("meta")) {
						if ("THUMBNAIL_URL".equalsIgnoreCase(xpp.getAttributeValue(null, "name"))) {
							String imageSrcUrl = xpp.getAttributeValue(null, "content");

							return imageSrcUrl;
						}
					}
				}
				eventType = xpp.next();
			}
		} catch (Throwable t) {
			t.printStackTrace();
		}

		return result;

	}

	private InputStream fetchInputStreamForURL(String url) {
		try {
			Log.e(TAG, "Invoking Webpage..Before");
			DefaultHttpClient client = new DefaultHttpClient();
			HttpGet httpMethod = new HttpGet(replaceHiWithMobile(url));
			HttpResponse response = client.execute(httpMethod);
			HttpEntity entity = response.getEntity();
			Log.e(TAG, "Invoking Webpage..After");
			return entity.getContent();
		} catch (ClientProtocolException e) {
			Log.e(TAG, " ClientProtocolException");
		} catch (IOException e) {
			Log.e(TAG, "IOException ");
		}
		return null;
	}

	private String replaceHiWithMobile(String url) {
		return url.replace("/hi/", "/mobile/");
	}

	class SwipeGestureDetector extends SimpleOnGestureListener {
		@Override
		public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
			// int delta = 0;
			if (Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH)
				return false;
			else {
				try {
					// right to left swipe
					if (e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
						if (canFlipRight()) {
							flipper.setInAnimation(mInFromRight);
							flipper.setOutAnimation(mOutToLeft);
							updateStateOfScreenWithClick(NEXT_CLICK);
							flipper.showNext();
						} else {
							return false;
						}
						// left to right swipe
					} else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
						if (canFlipLeft()) {
							flipper.setInAnimation(mInFromLeft);
							flipper.setOutAnimation(mOutToRight);
							updateStateOfScreenWithClick(PREV_CLICK);
							flipper.showPrevious();
						} else {
							return false;
						}
					}
				} catch (Exception e) {
					// nothing
				}
				return true;
			}
		}

		private boolean canFlipLeft() {

			return true;
		}

		private boolean canFlipRight() {

			return true;
		}
	}

	public String convertStreamToString(InputStream is) {
		/*
		 * To convert the InputStream to String we use the
		 * BufferedReader.readLine() method. We iterate until the BufferedReader
		 * return null which means there's no more data to read. Each line will
		 * appended to a StringBuilder and returned as String.
		 */
		BufferedReader reader = new BufferedReader(new InputStreamReader(is));
		StringBuilder sb = new StringBuilder();

		String line = null;
		try {
			while ((line = reader.readLine()) != null) {
				sb.append(line + "\n");
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				is.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

		return sb.toString();
	}

}
